/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.xd.service.impl;

import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.client.DocumentCodePoolClient;
import com.xy.biz.fd.client.DocumentCodeRuleClient;
import com.xy.biz.fd.domain.enums.DocumentDefaultRepositoryEnum;
import com.xy.biz.fd.domain.req.SaveDocumentCodePoolRequest;
import com.xy.biz.fd.domain.req.document.GetDocumentRequest;
import com.xy.biz.fd.domain.req.document.SaveDocumentRequest;
import com.xy.biz.fd.domain.req.documentCode.GetDocumentCodeRuleRequest;
import com.xy.biz.fd.domain.resp.GetDocumentCodeRuleResponse1;
import com.xy.biz.fd.domain.resp.GetDocumentResponse;
import com.xy.biz.mc.client.MessagePushClient;
import com.xy.biz.mc.domain.Message;
import com.xy.biz.mc.domain.consts.MessageTypeConstant;
import com.xy.biz.mc.domain.req.MessagePushRequest;
import com.xy.biz.xd.domain.bo.DocumentFlowHandleBO;
import com.xy.biz.xd.domain.bo.DocumentFlowNewAndModifyBO;
import com.xy.biz.xd.domain.bo.DocumentReleaseBO;
import com.xy.biz.xd.domain.converter.DocumentFlowNewAndModifyConverter;
import com.xy.biz.xd.domain.enums.DocumentFlowBatchTypeEnum;
import com.xy.biz.xd.domain.enums.DocumentReleaseStatusEnum;
import com.xy.biz.xd.domain.req.ApplyDocumentFlowModifyRequest;
import com.xy.biz.xd.domain.req.ReleaseDocumentFlowMotifyRequest;
import com.xy.biz.xd.domain.req.UploadDocumentFlowModifyRequest;
import com.xy.biz.xd.manager.DocumentFlowHandleManager;
import com.xy.biz.xd.manager.DocumentFlowNewAndModifyManager;
import com.xy.biz.xd.manager.DocumentReleaseManager;
import com.xy.biz.xd.service.DocumentFlowModifyService;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.tuples.Triple;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.json.JsonUtils;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.xy.biz.xd.domain.bo.DocumentFlowConstants.*;


/**
 *
 *
 * @author yzh
 * @date 2021-2-25
 */
@Service
public class DocumentFlowModifyServiceImpl extends AbstractDocumentFlowNewAndModifyServiceImpl implements DocumentFlowModifyService {

    @Autowired
    private DocumentClient documentClient;
    @Autowired
    private MessagePushClient messagePushClient;
    @Autowired
    private DocumentReleaseManager documentReleaseManager;
    @Autowired
    private DocumentCodeRuleClient documentCodeRuleClient;
    @Autowired
    private DocumentCodePoolClient documentCodePoolClient;
    @Autowired
    private DocumentFlowHandleManager documentFlowHandleManager;
    @Autowired
    private DocumentFlowServiceSupport documentFlowServiceSupport;
    @Autowired
    private DocumentFlowNewAndModifyManager documentFlowNewAndModifyManager;
    private final String type = "修订";

    @Override
    protected String getType() {
        return type;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> saveDocumentFlow(ApplyDocumentFlowModifyRequest request) {
        if(Objects.isNull(UserContextHolder.getUserGroupId())){
            return Result.ofBadRequest("用户部门缺失！");
        }
        List<DocumentFlowNewAndModifyBO> documentFlowNewAndModifyBOList = DocumentFlowNewAndModifyConverter.toBOList(request);
        DocumentFlowNewAndModifyBO documentFlowNewBO = buildNewDocumentFlowBO(documentFlowNewAndModifyBOList, FLOW_TYPE_MODIFY);
        Task task = documentFlowServiceSupport.startFirstTask(documentFlowNewBO, PROCESS_MODIFY_FLOW, documentFlowNewBO.getDocumentManagerUserId());
        //Task task = documentFlowServiceSupport.startFirstTask2(documentFlowNewBO, PROCESS_MODIFY_FLOW, documentFlowNewBO.getDocumentManagerUserIdList());
        String foreignKey = task.getProcessInstanceId();
        documentFlowNewBO.setForeignKey(foreignKey);
        int row = documentFlowNewAndModifyManager.saveAllDocumentFlowNewAndModify(documentFlowNewAndModifyBOList);
        if (row > 0) {
            //定义消息内容
            Message build = Message.builder()
                    .type(MessageTypeConstant.TYPE_FLOW)
                    .data(1)
                    .path(MessageTypeConstant.FLOW_LIST)
                    .remark("修订流程-申请审批")
                    .build();
            //发送消息
            messagePushClient.send(MessagePushRequest.builder()
                    .data(JsonUtils.toJson(build).getBytes())
                    .dataType(0)
                    .expiredSeconds(0L)
                    .toId(request.getDocumentManagerUserId())
                    .offlineFlag(true).build());
//            request.getDocumentManagerUserIdList().forEach(e -> {
//                messagePushClient.send(MessagePushRequest.builder()
//                        .data(JsonUtils.toJson(build).getBytes())
//                        .dataType(0)
//                        .expiredSeconds(0L)
//                        .toId(e)
//                        .offlineFlag(true).build());
//            });
        }
        return Result.success(documentFlowNewBO.getDocumentFlowId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> uploadDocumentFlow(UploadDocumentFlowModifyRequest request) {
        DocumentFlowNewAndModifyBO documentFlowNewAndModifyBO = documentFlowNewAndModifyManager.getDocumentFlowNewAndModify(request.getDocumentFlowId());
        List<UploadDocumentFlowModifyRequest.DocumentFlowInfo> documentFlowInfoList = request.getDocumentFlowInfoList();
        if (Objects.isNull(documentFlowNewAndModifyBO) || CollectionUtils.isEmpty(documentFlowInfoList)) {
            return Result.ofNotFound(String.valueOf(request.getDocumentFlowId()));
        }
        Map<String, Long> documentCodeMap = new HashMap<>();
        Map<String, Long> documentCodePreviousMap = documentFlowInfoList.stream().collect(Collectors.toMap(UploadDocumentFlowModifyRequest.DocumentFlowInfo::getDocumentCode, UploadDocumentFlowModifyRequest.DocumentFlowInfo::getPreviousDocumentId));
        if (Objects.equals(HANDLE_RESULT_ACCEPT, request.getResult())) {
            documentCodeMap = documentFlowInfoList.stream().collect(Collectors.toMap(UploadDocumentFlowModifyRequest.DocumentFlowInfo::getDocumentCode, UploadDocumentFlowModifyRequest.DocumentFlowInfo::getDocumentId));
            //锁定原文档
            Integer rows = ResultUtils.get(documentClient.updateDocumentByIds(SaveDocumentRequest
                    .builder()
                    .documentFlowLock(true)
                    .documentIds(new ArrayList<>(documentCodeMap.values()))
                    .build()));
            if (rows < 1) {
                return Result.fail("", "原文件不存在！");
            }
            documentClient.updateDocumentByIds(
                    SaveDocumentRequest.builder()
                            .latestVersionFlag(1)
                            .documentIds(new ArrayList<>(documentCodePreviousMap.values())).build());
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(
                    documentFlowNewAndModifyBO,
                    UserContextHolder.getUserId(),
                    PHASE_UPLOAD,
                    HANDLE_RESULT_ACCEPT, request.getOpinion());
            documentFlowHandleManager.saveAllDocumentFlowHandle(Collections.singletonList(documentFlowHandleBO));
            documentFlowNewAndModifyBO.setPhase(PHASE_EDIT);
            documentFlowServiceSupport.gotoNextTask(documentFlowNewAndModifyBO, request.getEditUserId(), request.getResult());
        } else {
            DocumentFlowHandleBO documentFlowHandleBO = DocumentFlowHandleBO.build(
                    documentFlowNewAndModifyBO,
                    UserContextHolder.getUserId(),
                    PHASE_UPLOAD,
                    HANDLE_RESULT_REJECT, request.getOpinion());
            documentFlowHandleManager.saveAllDocumentFlowHandle(Collections.singletonList(documentFlowHandleBO));
            documentFlowNewAndModifyBO.setPhase(PHASE_REJECT);
            documentFlowServiceSupport.gotoNextTask(documentFlowNewAndModifyBO, null, request.getResult());

            GetDocumentCodeRuleResponse1 response1 = ResultUtils.get(documentCodeRuleClient.getCodeInfo(GetDocumentCodeRuleRequest.builder().code(documentFlowNewAndModifyBO.getDocumentCode()).build()));
            if (Objects.isNull(response1)) {
                return Result.fail();
            }
            LocalDateTime now = LocalDateTime.now();
            if (documentFlowInfoList.size() > 1) {
                List<SaveDocumentCodePoolRequest> documentCodePoolRequestList = new ArrayList<>();
                documentFlowInfoList.forEach(e -> {
                    documentCodePoolRequestList.add(SaveDocumentCodePoolRequest
                            .builder()
                            .documentCode(e.getDocumentCode())
                            .reuseFlag(true)
                            .updateTime(now)
                            .build());
                });
                documentCodePoolClient.updateAllDocumentCodePoolByCode(documentCodePoolRequestList);
            } else {
                SaveDocumentCodePoolRequest req = SaveDocumentCodePoolRequest.builder()
                        .documentCode(documentFlowNewAndModifyBO.getDocumentCode())
                        .reuseFlag(true)
                        .updateTime(now)
                        .build();
                documentCodePoolClient.updateDocumentCodePool(req);
            }
        }
        List<DocumentFlowNewAndModifyBO> documentFlowNewAndModifyBOList = buildUploadDocumentFlowNewAndModifyBO(documentFlowNewAndModifyBO, documentCodeMap, documentCodePreviousMap);
        int row = documentFlowNewAndModifyManager.updateAllDocumentFlowNewAndModify(documentFlowNewAndModifyBOList);
        if (row > 0) {
            //定义消息内容
            Message message = Message.builder()
                    .type(MessageTypeConstant.TYPE_FLOW)
                    .path(MessageTypeConstant.FLOW_LIST)
                    .build();
            Long toId;
            //通过的信息
            if (Objects.equals(HANDLE_RESULT_ACCEPT, request.getResult())) {
                message.setRemark("修订流程-文件编辑");
                message.setData(1);
                toId = request.getEditUserId();
            } else {//不通过的信息
                message.setRemark("修订流程-模板上传管理拒绝申请");
                message.setData(0);
                //获取申请人
                toId = getApplyUserId(request.getDocumentFlowId(), PHASE_APPLY);
            }
            //发送消息
            sendMessage(message, toId);
        }
        return Result.success();
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> releaseDocumentFlow(ReleaseDocumentFlowMotifyRequest request) {
        DocumentFlowNewAndModifyBO documentFlowBO = documentFlowNewAndModifyManager.getDocumentFlowNewAndModify(request.getDocumentFlowId());
        if (Objects.isNull(documentFlowBO)) {
            return Result.ofNotFound(String.valueOf(request.getDocumentFlowId()));
        }
        Integer batchType = documentFlowBO.getBatchType();
        Result<Triple<List<DocumentFlowNewAndModifyBO>, List<Long>, List<Long>>> result;
        if (!(result = saveDocumentReleaseList(request, documentFlowBO, batchType)).wasSuccess()) {
            return result;
        }
        Triple<List<DocumentFlowNewAndModifyBO>, List<Long>, List<Long>> triple = ResultUtils.get(result);
        List<DocumentFlowNewAndModifyBO> documentFlowNewAndModifyBOList = triple.getValue1();
        List<Long> previousDocumentIdList = documentFlowNewAndModifyBOList.stream().map(DocumentFlowNewAndModifyBO::getPreviousDocumentId).collect(Collectors.toList());
        List<DocumentReleaseBO> documentReleaseList = new ArrayList<>();
        for (DocumentFlowNewAndModifyBO documentFlowNewAndModifyBO : documentFlowNewAndModifyBOList) {
            documentReleaseList.add(DocumentReleaseBO
                    .builder()
                    .documentId(documentFlowNewAndModifyBO.getPreviousDocumentId())
                    .documentVersion(documentFlowNewAndModifyBO.getPreviousDocumentVersion())
                    .updateTime(LocalDateTime.now())
                    .status(DocumentReleaseStatusEnum.OVER_TIME.getCode())
                    .build());
        }
        documentReleaseManager.updateAllDocumentRelease(documentReleaseList);
        List<SaveDocumentRequest> saveDocumentRequestList = new ArrayList<>();
        if (batchType.equals(DocumentFlowBatchTypeEnum.UNBATCH.getCode())) {
            //修改旧版本文档信息
            GetDocumentResponse preDocument = ResultUtils.get(documentClient.getDocument(GetDocumentRequest.builder().documentId(documentFlowBO.getPreviousDocumentId()).build()));
            SaveDocumentRequest saveDocumentRequest = buildRequest(documentFlowBO, request.getOpinion());
            saveDocumentRequest.setThreadId(preDocument.getThreadId());
            saveDocumentRequest.setLevel(preDocument.getLevel());
            saveDocumentRequestList.add(saveDocumentRequest);
        } else {
            Map<Long, GetDocumentResponse> previousDocumentMap = new HashMap<>();
            Map<Long, GetDocumentResponse> documentMap = new HashMap<>();
            if (CollectionUtils.isEmpty(previousDocumentIdList)) {
                previousDocumentMap.putAll(ResultUtils.get(documentClient.listDocumentById(previousDocumentIdList))
                        .stream().collect(Collectors.toMap(GetDocumentResponse::getDocumentId, e -> e)));
            }
            for (DocumentFlowNewAndModifyBO documentFlowNewAndModifyBO : documentFlowNewAndModifyBOList) {
                if (previousDocumentMap.containsKey(documentFlowNewAndModifyBO.getPreviousDocumentId())) {
                    documentMap.put(documentFlowNewAndModifyBO.getDocumentId(), previousDocumentMap.get(documentFlowNewAndModifyBO.getDocumentId()));
                }
            }
            triple.getValue1().forEach(e -> saveDocumentRequestList.add(buildRequest(e, request.getOpinion())));
            saveDocumentRequestList.forEach(e -> {
                if (documentMap.containsKey(e.getDocumentId())) {
                    GetDocumentResponse documentResponse = documentMap.get(e.getDocumentId());
                    //旧文件设置为作废
                    e.setRepositoryId(DocumentDefaultRepositoryEnum.OBSOLETE_REPOSITORY.getCode());
                    e.setLatestVersionFlag(1);
                    e.setThreadId(documentResponse.getThreadId());
                    e.setLevel(documentResponse.getLevel());
                }
            });
        }
        //更新 新旧文档信息
        documentClient.updateAllDocument(saveDocumentRequestList);
        //完善培训信息
        documentFlowBO.setTrainFlag(request.getTrainFlag());
        documentFlowBO.setTrainCheckStatus(0);
        documentFlowBO.setTrainerUserId(request.getTrainerUserId());
        documentFlowBO.setPhase(PHASE_RELEASE);
        int row = documentFlowNewAndModifyManager.updateDocumentFlowNewAndModify(documentFlowBO);
        if (row > 0) {
            //定义消息内容
            Message message = Message.builder()
                    .type(MessageTypeConstant.TYPE_FLOW)
                    .data(0)
                    .remark("修订一条新的放行文件-去签收")
                    .path(MessageTypeConstant.DOCUMENT_RELEASE_CHECK)
                    .build();
            //发送消息
            Set<Long> userIdSet = buildMessageReceiveUserIdCollection(triple.getValue2(), triple.getValue3());
            for (Long userId : userIdSet) {
                sendMessage(message, userId);
            }
        }
        return Result.success();
    }
}
